// Copyright (C) 2004 Naoyuki Hirayama.
// All Rights Reserved.

// $Id: mqoreader.hpp 32 2008-10-25 12:19:56Z Naoyuki.Hirayama $

#if !defined(MQOREADER_HPP)
#define MQOREADER_HPP

// module: 

#include <stdexcept>
#include <string>
#include <map>
#include <vector>
#include <iosfwd>

namespace mqo_reader {

struct mqo_reader_error : public std::runtime_error {
    mqo_reader_error(const std::string& s) : std::runtime_error(s){}
};

struct color_type {
    float   red;
    float   green;
    float   blue;
    float   alpha;
};

enum shader_type {
    shader_classic  =0,
    shader_constant =1,
    shader_lambert  =2,
    shader_phong    =3,
    shader_blinn    =4,
};

enum projection_type {
    projection_uv       =0,
    projection_plane    =1,
    projection_cylinder =2,
    projection_sphere   =3,
};

struct vector_type {
    float x;
    float y;
    float z;
};

struct projangle_type {
    float heading;
    float pitching;
    float banking;
};

struct material_type {
    std::string     name;
    shader_type     shader;
    bool            vertex_color;
    color_type      color;
    float           diffuse;
    float           ambient;
    float           emissive;
    float           specular;
    float           power;
    std::string     texture;
    std::string     aplane;
    std::string     bump;
    projection_type projection;
    vector_type     proj_pos;
    vector_type     proj_scale;
    projangle_type  proj_angle;
};
typedef std::vector< material_type > materials_type;

enum patch_type {
    patch_plane         =0,
    patch_spline1       =1,
    patch_spline2       =2,
    patch_catmull_clark =3,
};

enum shading_type {
    shading_flat        =0,
    shading_gouraud     =1,
};

enum edgecolor_type {
    edgecolor_environment   =0,
    edgecolor_object        =1,
};

enum mirror_type {
    mirror_none             =0,
    mirror_connect          =1,
    mirror_divide           =2,
};

enum mirroraxis_type {
    mirroraxis_none         =0,
    mirroraxis_x            =1,
    mirroraxis_y            =2,
    mirroraxis_z            =4,
};

enum lathe_type {
    lathe_none              =0,
    lathe_double            =3,
};

enum latheaxis_type {
    latheaxis_x             =0,
    latheaxis_y             =1,
    latheaxis_z             =2,
};

struct vertex_type {
    float x;
    float y;
    float z;
};
typedef std::vector< vertex_type >      vertices_type;

struct uv_type {
    float u;
    float v;
};

struct face_type {
    int             vertex_count;
    int             vertex_indices[4];
    int             material_index;
    uv_type         uv[4];
    color_type      colors[4];
};
typedef std::vector< face_type >        faces_type;

struct object_type {
    std::string     name;
    int             depth;
    bool            folding;
    vector_type     scale;
    vector_type     rotation;
    vector_type     translation;
    patch_type      patch;
    int             segment;
    bool            visible;
    bool            locking;
    shading_type    shading;
    float           facet;
    color_type      color;
    edgecolor_type  color_type;
    mirror_type     mirror;
    mirroraxis_type mirror_axis;
    float           mirror_dis;
    lathe_type      lathe;
    latheaxis_type  lathe_axis;
    int             lathe_seg;

    vertices_type   vertices;
    faces_type      faces;
};
typedef std::map< std::string, object_type > objdic_type;

struct scene_type {
    color_type      ambient;        
};

struct document_type {
    int major_version;
    int minor_version;

    scene_type      scene;
    objdic_type     objects;
    materials_type  materials;
};

void read_mqo(std::istream&,document_type&);

}

#endif
